﻿using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Events;
using Serilog.Filters;
using Serilog.Sinks.MSSqlServer;
using System.Collections.ObjectModel;
using System.Data;

namespace TransformerManager.API.LogSettings
{
    /// <summary>
    /// Serilog配置类
    /// </summary>
    public class SerilogConfiguration
    {
        public static void CreateLogger()
        {
            IConfigurationRoot configuration = new ConfigurationBuilder()
                .AddJsonFile(
                "appsettings.json",
                optional: false,
                reloadOnChange: true
                ).Build();

            string connectionString = configuration["DbContext:ConnectionString"]; // 数据库连接字符串
            const string tableName = "OperationLogs";
            var columnOpts = new ColumnOptions // 自定义字段
            {
                AdditionalColumns = new Collection<SqlColumn>
                {
                    new SqlColumn {DataType = SqlDbType.VarChar, ColumnName = "OperationType"},
                    new SqlColumn {DataType = SqlDbType.VarChar, ColumnName = "UserName"},
                    new SqlColumn {DataType = SqlDbType.VarChar, ColumnName = "IP"},
                    new SqlColumn {DataType = SqlDbType.VarChar, ColumnName = "RequestPath"},
                    new SqlColumn {DataType = SqlDbType.VarChar, ColumnName = "RequestBody"}
                }
            };
            // Sql Server的表中加入Json格式Log Event的数据字段
            columnOpts.Store.Add(StandardColumn.LogEvent);
            // 输出模板，Sql Server不能用这个
            const string outputTemplate = "[{Timestamp:HH:mm:ss.FFF} {Level}] {UserName} {Message} {Exception} \n";
            
            Serilog.Log.Logger = new LoggerConfiguration()

                .WriteTo.Logger(l =>
                {
                    l.MinimumLevel.Warning(); // 所有Sink的最小记录级别
                    l.WriteTo.Console(outputTemplate: outputTemplate);
                })

                .WriteTo.Logger(l =>
                {
                    l.MinimumLevel.Warning(); // 所有Sink的最小记录级别
                    l.WriteTo.Debug(outputTemplate: outputTemplate);
                })

                .WriteTo.Logger(l=>
                {
                    l.MinimumLevel.Information()
                    .Filter.ByIncludingOnly(Matching.FromSource("TransformerManager.API"))
                    .WriteTo.File(@"Logs\Operationlogs.txt",
                        rollOnFileSizeLimit:true,
                        fileSizeLimitBytes: 5242880,
                        retainedFileCountLimit: null);
                })

                .WriteTo.Logger(l=>
                {
                    l.MinimumLevel.Information()
                    .Enrich.FromLogContext() //动态加入属性，主要是针对上面的自定义字段。
                    .Filter.ByIncludingOnly(Matching.WithProperty<string>("UserName", u => !string.IsNullOrEmpty(u) || u != "unknown"))
                    .Filter.ByIncludingOnly(Matching.WithProperty<string>("RequestPath", r => r.Contains("/api/v")))
                    .Filter.ByIncludingOnly(Matching.WithProperty<string>("EndpointName", m => m.Contains("TransformerManager.API.Controllers.TransformersController")))
                    .Filter.ByExcluding(Matching.WithProperty<string>("OperationType", o => string.IsNullOrEmpty(o) || o.Contains("GET")))
                    .WriteTo.MSSqlServer(
                        connectionString: configuration["DbContext:ConnectionString"],
                        sinkOptions: new MSSqlServerSinkOptions()
                        {
                            TableName = tableName,
                            AutoCreateSqlTable = true
                        },
                        columnOptions: columnOpts,
                        restrictedToMinimumLevel: LogEventLevel.Information
                        );
                }).CreateLogger();
        }
    }
}
